#include "stdafx.h"
#include "scene.h"
#include "automatic_item.h"

SceneView::SceneView(Common* _common)
	: common(_common)
{
	this->setBackgroundBrush(QBrush(QColor(49, 77, 116)));
	//this->setBackgroundBrush(QBrush(QColor(240, 240, 240)));
	redraw_virtual_connector = false;
}

SceneView::~SceneView() {
	delete virtual_item;
	delete virtual_connector;
}

void SceneView::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent){
	update();
	QGraphicsScene::mousePressEvent(mouseEvent);
}

void SceneView::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent){
	if (redraw_virtual_connector){
		virtual_connector->adjust(mouseEvent->scenePos());
		if (virtual_connector->isHydraulic()) redrawVirtualHydConnector(mouseEvent->scenePos());
		if (virtual_connector->isAutomatic()) redrawVirtualAutConnector(mouseEvent->scenePos());
	}
	update();
	QGraphicsScene::mouseMoveEvent(mouseEvent);
}

void SceneView::redrawVirtualHydConnector(const QPointF &pos){

	foreach(hydraulicItem* item, hydraulic_item_list){
		foreach(hydConPoint* point, item->getListOfhydConPoint()){
			QPointF distance = point->pos() - pos;
			point->setAccepted((point->isAllowedAddConnector() && abs(distance.x()) < 10 && abs(distance.y()) < 10));
			point->update();
		}
	}
	bool find_intersect = false;
	pair<QPointF, int > intersect_param;

	foreach(hydConnector* connector, hyd_connector_list)
		if (!virtual_connector->getHydSource()->isChild(connector)){
			intersect_param = connector->intersected(pos);
			if (intersect_param.second != -1){
				if (!findInnerNodeNearMouse(pos)){
					find_intersect = true;				
					break;
				}
			}
		}
	
	if (find_intersect){
		if (virtual_item == NULL){
			virtual_item = new hydraulicItem(this, hydraulicItem::INNER_NODE);
			addItem(virtual_item);
		}
		virtual_item->setPos(intersect_param.first);
	}else{
		removeItem(virtual_item);
		virtual_item = NULL;
	}
}

void SceneView::redrawVirtualAutConnector(const QPointF &pos){
	foreach(automaticItem* item, automatic_item_list){
		foreach(autConPoint* point, item->getListOfAutConPoint()){
			QPointF distance = point->pos() - pos;
			point->setAccepted((point->isAllowedAddConnector() && abs(distance.x()) < 10 && abs(distance.y()) < 10));
			point->update();
		}
	}
}

bool SceneView::findInnerNodeNearMouse(const QPointF &_pos){
	foreach(hydraulicItem* item, hydraulic_item_list){
		if (item->getType() == hydraulicItem::INNER_NODE){
			QPointF distance = item->pos() - _pos;
			if (abs(distance.x()) < 25 && abs(distance.y()) < 25) return true;
		}
	}
	return false;
}

void SceneView::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent){
	if(redraw_virtual_connector){
		redraw_virtual_connector = false;
		if (virtual_connector->isHydraulic()) releaseVirtualHydConnector(mouseEvent->scenePos());
		if (virtual_connector->isAutomatic()) releaseVirtualAutConnector(mouseEvent->scenePos());
		removeItem(virtual_connector->getLine());
		virtual_connector = NULL;
	}
	update();
	QGraphicsScene::mouseReleaseEvent(mouseEvent);
}

void SceneView::releaseVirtualHydConnector(const QPointF &pos){
	bool find_point = false;
	hydConPoint *source_point = virtual_connector->getHydSource();
	//removeItem(virtual_item);
	//virtual_item = NULL;
 	
 	
	foreach(hydraulicItem* item, hydraulic_item_list){
		foreach(hydConPoint* dest_point, item->getListOfhydConPoint()){
			if(!find_point && dest_point->isAccepted() && dest_point != source_point){
				addHydConnector(source_point, dest_point);
				find_point = true;
			}
			dest_point->setVisible(false);
			dest_point->setAccepted(false);
		}
		item->setFlag(QGraphicsItem::ItemIsMovable);
		item->setFlag(QGraphicsItem::ItemIsSelectable);
	}
	
	if (!find_point){
		pair<QPointF, int > intersect_param;
		for(int i = 0; i < hyd_connector_list.size(); i++){
			hydConnector* connector = hyd_connector_list[i];
			if (!source_point->isChild(connector)){
				intersect_param = connector->intersected(pos);
				if (intersect_param.second != -1){
					if (!findInnerNodeNearMouse(pos)){
						hydraulicItem* item = addHydraulicItem(intersect_param.first, hydraulicItem::INNER_NODE);
						cutConnector(i, item->getListOfhydConPoint()[0]);
						addHydConnector(source_point, item->getListOfhydConPoint()[0]);
						break; break;
					}
				}
			}
		}
		foreach(hydConnector* connector, hyd_connector_list)
			connector->setMovable(true);
	}
}

void SceneView::releaseVirtualAutConnector(const QPointF &pos){
	bool find_point = false;
	autConPoint *source_point = virtual_connector->getAutSource();
	foreach(automaticItem* item, automatic_item_list){
		foreach(autConPoint* dest_point, item->getListOfAutConPoint()){
			if(!find_point && dest_point->isAccepted() && dest_point != source_point){
				addAutConnector(source_point, dest_point);
				find_point = true;
			}
			dest_point->setVisible(false);
			dest_point->setAccepted(false);
		}
		item->setFlag(QGraphicsItem::ItemIsMovable);
		item->setFlag(QGraphicsItem::ItemIsSelectable);
	}
		foreach(autConnector* connector, aut_connector_list)
			connector->setMovable(true);
}

void SceneView::keyPressEvent(QKeyEvent *event){
	switch (event->key()) {
	case Qt::Key_Delete :
		DeleteSelectedItem();
		break;
	}
}

void SceneView::keyReleaseEvent(QKeyEvent *event){
	
}

void SceneView::dragEnterEvent(QGraphicsSceneDragDropEvent *event){
	if (dropped_item != 5){
		virtual_item = new hydraulicItem(this, dropped_item);
		addItem(virtual_item);
	}else{
		virtual_automatic_item = new automaticItem(this, hydraulicItem::itemType_t(1));
		addItem(virtual_automatic_item);
	}
}

void SceneView::dragMoveEvent(QGraphicsSceneDragDropEvent *event){
	if (dropped_item != 5){
		virtual_item->setPos(event->scenePos());
		virtual_item->update();
	}else{
		virtual_automatic_item->setPos(event->scenePos());
		virtual_automatic_item->update();
	}
}

void SceneView::dropEvent(QGraphicsSceneDragDropEvent *event){
	if (dropped_item != 5){
		removeItem(virtual_item);
		addHydraulicItem(event->scenePos(), dropped_item);
	}else{
		removeItem(virtual_automatic_item);
		addAutomaticItem(event->scenePos(), hydraulicItem::itemType_t(1));
	}
}

void SceneView::dragLeaveEvent(QGraphicsSceneDragDropEvent *event){
	if (dropped_item != 5){
		removeItem(virtual_item);
	}else{
		removeItem(virtual_automatic_item);
	}
}

hydraulicItem* SceneView::addHydraulicItem(const QPointF &_pos, const int &_type, const QString &_name, const bool &_visibleTitle){
	if ((int)_type < 0)	return NULL;
	hydraulicItem* item = new hydraulicItem(this, _type, _name, _pos);
	//item->setTitle(new Title(this, item, QPointF(0, - item->getSize().height() / 2), true,  "", item->getStringType()));
	//QStringList parameters;
	//parameters = g_units.getCalcParameters();
/*
	if (_type != (int)hydraulicItem::PIPE){
		QString parent_name = item->getTitleText();
		automaticItem *aut_item = new automaticItem(this, automaticItem::SENSOR, _name, QPointF(0,0));
		aut_item->setVisible(false);
		//Sensor* sensor = new Sensor(common, this, parent_name, parent_name, false, parameters);
		//sensor->getGraphicalItem()->setVisible(false);
		Indicator* indicator = new Indicator(common, this, aut_item, QPointF(0, 50), false, aut_item->getSensor()->getCalculatedParameters());
		indicator->setIndicatorVisible(true);
		aut_item->setIndicator(indicator);
		item->setAutomaticItem(aut_item);
	}*/
	item->setPosition(_pos);
	hydraulic_item_list.push_back(item);
	return item;
}

automaticItem* SceneView::addAutomaticItem(const QPointF &_pos, const int &_type, const QString &_parent_name, const QString &_name, const bool &_visibleTitle){
	if ((int)_type < 0)	return NULL;
	automaticItem * item = new automaticItem(this, _type, _name, _pos, _parent_name);
//	item->setTitle(new Title(this, item, QPointF(0, - item->getSize().height() / 2), "", item->getStringType()));
	item->setIndicator(new Indicator(common, this, item, QPointF(0, 50), true, item->getParameters()));
	item->setPosition(_pos);
	automatic_item_list.push_back(item);
	return item;
}

hydConnector* SceneView::addHydConnector(hydConPoint* _source, hydConPoint* _dest, const QString &_coordinates, const QPointF &_spot_pos){
	//Spot* spot = new Spot(this);
	//spot->setTitle(new Title(this, spot, QPointF(0, -8), "", "S"));
	//QStringList parameters = g_units.getCalcParameters();
/*
	automaticItem *aut_item = new automaticItem(this, automaticItem::SENSOR, spot->getTitleText(), QPointF(0, 0));
	aut_item->setVisible(false);
	Indicator* indicator = new Indicator(common, this, aut_item, QPointF(0, 50), false, aut_item->getSensor()->getCalculatedParameters());
	indicator->setIndicatorVisible(true);
	aut_item->setIndicator(indicator);
	spot->setAutomaticItem(aut_item);*/

	hydConnector* connector = new hydConnector(this, _source, _dest, _coordinates);
	//connector->setConPoint();
	connect(_source, SIGNAL(posChanged(const QPointF&)), connector, SLOT(setSourcePoint(const QPointF&)));
	connect(_dest, SIGNAL(posChanged(const QPointF&)), connector, SLOT(setDestPoint(const QPointF&)));
	//spot->addSource(connector);
	//QPointF spot_pos = (_spot_pos != QPointF()) ? _spot_pos : connector->getMiddlePoint();
	//spot->setPos(spot->findClosestPoint(spot_pos));
	
	hyd_connector_list.push_back(connector);
	_source->addConnector(connector);
	_dest->addConnector(connector);
	return connector;
}

autConnector* SceneView::addAutConnector(autConPoint* _source, autConPoint* _dest, const QString &_coordinates, const QPointF &_spot_pos){
	autConnector* connector = new autConnector(this, _source, _dest, _coordinates);
	connect(_source, SIGNAL(posChanged(const QPointF&)), connector, SLOT(setSourcePoint(const QPointF&)));
	connect(_dest, SIGNAL(posChanged(const QPointF&)), connector, SLOT(setDestPoint(const QPointF&)));
	aut_connector_list.push_back(connector);
	_source->addConnector(connector);
	_dest->addConnector(connector);
	return connector;
}

void SceneView::cutConnector(int index, hydConPoint* point){
	if (index >= 0 && index < hyd_connector_list.size()){
		hydConnector* connector = hyd_connector_list[index];
		pair<QPointF, int > intersect_param = connector->intersected(point->pos());
		if (intersect_param.second != -1){	
			QString coordinates = connector->get_lines_coordinate(intersect_param.second, intersect_param.first);
			connector->getDest()->removeConnector(connector);
			addHydConnector(point, connector->getDest(), coordinates);
			connector->setDest(point);
			point->addConnector(connector);
			for (int i = connector->lines.size() - 1;  i > intersect_param.second; i--){
				delete connector->lines[i];
				connector->lines.erase(connector->lines.begin() + i);		
			}

			connector->lines[intersect_param.second]->dest = intersect_param.first;
			//connector->spot->setPos(connector->spot->findClosestPoint(connector->getMiddlePoint()));	
		}
	}
}


void SceneView::addVirtualHydConnector(hydConPoint* _point){
	virtual_connector = new virtualConnector(this, _point, _point->pos());
	foreach(hydraulicItem* item, hydraulic_item_list){
		foreach(hydConPoint* point, item->getListOfhydConPoint()){
			if (point->isAllowedAddConnector())
				point->setVisible(true);
		}
		item->setFlag(QGraphicsItem::ItemIsMovable, false);
		item->setFlag(QGraphicsItem::ItemIsSelectable, false);
	}
	
	foreach(hydConnector* connector, hyd_connector_list)
		connector->setMovable(false);
	redraw_virtual_connector = true;
}


void SceneView::addVirtualAutConnector(autConPoint* _point){
	virtual_connector = new virtualConnector(this, _point, _point->pos());
	foreach(automaticItem* item, automatic_item_list){
		foreach(autConPoint* point, item->getListOfAutConPoint()){
			if (point->isAllowedAddConnector())
				point->setVisible(true);
		}
		item->setFlag(QGraphicsItem::ItemIsMovable, false);
		item->setFlag(QGraphicsItem::ItemIsSelectable, false);
	}
	foreach(autConnector* connector, aut_connector_list)
		connector->setMovable(false);
	redraw_virtual_connector = true;
}

void SceneView::DeleteSelectedItem(){
	foreach(hydraulicItem* item, hydraulic_item_list)
		if (item->isSelected()){
			//eraseHydItemFromList(item);
			delete item;
		}
	foreach(automaticItem* item, automatic_item_list)
		if (item->isSelected()){
			//eraseAutItemFromList(item);
			delete item;
		}
}

void SceneView::eraseHydItemFromList(hydraulicItem* item){
	hydraulic_item_list.erase(find(hydraulic_item_list.begin(), hydraulic_item_list.end(), item));
	//delete item;
}
void SceneView::eraseAutItemFromList(automaticItem* item){
	automatic_item_list.erase(find(automatic_item_list.begin(), automatic_item_list.end(), item));
	//delete item;
}

void SceneView::eraseHydConnectorFromList(hydConnector* connector){
	hyd_connector_list.erase(find(hyd_connector_list.begin(), hyd_connector_list.end(), connector));
	delete connector;
}

void SceneView::eraseAutConnectorFromList(autConnector* connector){
	aut_connector_list.erase(find(aut_connector_list.begin(), aut_connector_list.end(), connector));
	delete connector;
}

hydraulicItem* SceneView::findHydItemByName(const QString &_name){
	foreach(hydraulicItem* item, hydraulic_item_list){
		if(item->getTitleText() == _name)
			return item;
	}
	return NULL;
}

automaticItem* SceneView::findAutItemByName(const QString &_name){
	foreach(automaticItem* item, automatic_item_list){
		if(item->getTitleText() == _name)
			return item;
	}
	return NULL;
}

hydConnector* SceneView::findHydConnectorByName(const QString &_name){
	foreach(hydConnector* connector, hyd_connector_list){
		/*if(connector->spot->getTitleText() == _name)
			return connector;*/
	}
	return NULL;
}

Sensor* SceneView::findSensorByName(const QString &_item_name, const QString &_sensor_name){
/*
	hydraulicItem *item = findItemByName(_item_name);
	if (item != NULL){
		if (item->getType() != hydraulicItem::PIPE){
			/ *if (item->getAutomaticItem()->getSensor()->getName() == _sensor_name)
				return item->getAutomaticItem()->getSensor();* /
		}else{
			foreach(automaticItem *aut_item, item->getAutomaticItemList())
				if (aut_item->getSensor()->getName() == _sensor_name)
					return aut_item->getSensor();
		}
	}else{
		Connector *connector = findConnectorByName(_item_name);
		if (connector != NULL)
			if (connector->spot->getAutomaticItem()->getSensor()->getName() == _sensor_name)
				return connector->spot->getAutomaticItem()->getSensor();
	}*/
	return NULL;
}


int SceneView::getIndexInList(hydraulicItem *item){
	for(int i = 0; i < hydraulic_item_list.size(); i++)
		if(item == hydraulic_item_list[i])
			return i;
	return -1;
}

void SceneView::indexDroppedItemChanged( int index ){
	dropped_item = (hydraulicItem::itemType_t)index;
}

QStringList SceneView::getItemsName(){
	QStringList list;
	foreach(hydraulicItem *item, hydraulic_item_list)
		list.push_back(item->getTitleText());
	/*foreach(Connector *connector, hyd_connector_list)
		list.push_back(connector->spot->getTitleText());*/
	return list;
}

QStringList SceneView::getAutItemsNameWithParameters(){
	QStringList list;
	/*foreach(automaticItem *item, automatic_item_list){
		if (item->getSensor() != NULL && item->getSensor()->countCalcParameters()){
			list.push_back(item->getTitleText());
		}
	}*/
	foreach(automaticItem *item, automatic_item_list){
		if (item->getParameters().size()){
			if (item->isSensor()){
				if (item->getSensor()->countCalcParameters()) list.push_back(item->getTitleText());
			}else{
				list.push_back(item->getTitleText());
			}
		}
	}
	return list;
}

QStringList SceneView::getSensorsName(const QString &item_name){
	QStringList list;
	/*hydraulicItem *item = findItemByName(item_name);
	if (item != NULL){
		if (item->getType() != hydraulicItem::PIPE){
			//list.push_back(item->getAutomaticItem()->getSensor()->getName());
		}else{
			foreach(automaticItem *aut_item, item->getAutomaticItemList())
				list.push_back(aut_item->getSensor()->getName());
		}
	}else{
		Connector *connector = findConnectorByName(item_name);
		if (connector != NULL)
			list.push_back(connector->spot->getAutomaticItem()->getSensor()->getName());
	}*/
	return list;
}

bool SceneView::isUniqueName(QGraphicsObject* item, const QString &_name) const{
	foreach (hydraulicItem* hyd_item, hydraulic_item_list)
		if(item != hyd_item)
			if (hyd_item->getTitleText() == _name)
				return false;
	foreach (automaticItem* aut_item, automatic_item_list)
		if(item != aut_item)
			if (aut_item->getTitleText() == _name)
				return false;
	return true;
}
